package hhf.net {
	import flash.events.StatusEvent;

	CONFIG::air {
		import air.net.SocketMonitor;
	}
	CONFIG::flex {
		import flash.events.StatusEvent;
		import flash.utils.clearTimeout;
		import flash.utils.setTimeout;

		import mx.rpc.events.FaultEvent;
		import mx.rpc.events.ResultEvent;
		import mx.rpc.http.HTTPService;
	}

	import mx.core.FlexGlobals;

	public class NetworkMonitor {

		CONFIG::air {
			protected static var monitor:SocketMonitor;
		}
		CONFIG::flex {
			protected static var monitor:mx.rpc.http.HTTPService;
		}
		protected static var currentPort:Number = 80;
		protected static var port:Number = 80;
		protected static var host:String = "127.0.0.1";
		protected static var pollInterval:Number = 2000;
		protected static var _available:Boolean = true;
		private static var firstCall:Boolean = true;
		CONFIG::flex {
			protected static var protocol:String = "http";
			protected static var timeout:uint = 0;
		}

		public static function get available():Boolean {
			return _available;
		}

		public static function set available(available:Boolean):void {
			if(available!=_available || firstCall) {
				firstCall = false;
				_available = available;
				trace("Network available : "+available);
				CONFIG::flex {
					var srv:String = available?"Service.available":"Service.unavailable";
					var event:StatusEvent = new StatusEvent(StatusEvent.STATUS, true, false, srv, "status");
					FlexGlobals.topLevelApplication.dispatchEvent(event);
				}
			}
			CONFIG::flex {
				timeout = setTimeout(NetworkMonitor.monitor.send, (available)?NetworkMonitor.pollInterval:500);
			}
		}

		public static function start(host:String=null, port:Number=NaN, pollInterval:Number=NaN):void {
			if (monitor == null) {
				NetworkMonitor.host = host;
				NetworkMonitor.port = port;
				NetworkMonitor.currentPort = port;
				NetworkMonitor.pollInterval = pollInterval;
				createAndStartMonitor();
			}
		}

		protected static function stop():void {
			CONFIG::air {
				if(monitor && monitor.running) monitor.stop();
			}
			CONFIG::flex {
				if(timeout) clearTimeout(timeout);
			}
		}

		protected static function createAndStartMonitor():void {
			CONFIG::air {
				monitor = new SocketMonitor(host, currentPort);
				monitor.addEventListener(StatusEvent.STATUS,
					function(event:StatusEvent):void {
						NetworkMonitor.available = NetworkMonitor.monitor.available;
						FlexGlobals.topLevelApplication.dispatchEvent(event);
					}
				);
				monitor.pollInterval = pollInterval;
				monitor.start();
			}
			CONFIG::flex {
				monitor = new HTTPService();
				monitor.url=protocol+"://"+host+":"+currentPort;
				monitor.addEventListener(ResultEvent.RESULT, function(event:ResultEvent):void {
					NetworkMonitor.available = true;
				});
				monitor.addEventListener(FaultEvent.FAULT, function(event:FaultEvent):void {
					trace("request unavailable code : "+event.statusCode);
					NetworkMonitor.available = event.statusCode != 0;
				});
				monitor.send();
			}
		}

		public static function changeNetwork():void {
			if(currentPort==port) currentPort = NaN;
			else currentPort = port;
			NetworkMonitor.stop();
			createAndStartMonitor();
		}
	}
}